/*
 moxl - Modular XML Library
 Copyright (c) 2007, Malcolm Sparks

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package moxl.reader;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;

public class XmlReader extends LocateableReader
{
	private String encoding;

	public XmlReader(String string) throws IOException
	{
		this(new ByteArrayInputStream(string.getBytes("UTF-8")));
	}

	public XmlReader(InputStream inputStream) throws IOException
	{
		InputStream wrapper = inputStream;
		if (!inputStream.markSupported())
		{
			wrapper = new BufferedInputStream(inputStream);
		}
		wrapper.mark(3);
		byte[] bom = new byte[3];
		int bomLength = wrapper.read(bom, 0, 3);
		if (isUtf8Bom(bom, bomLength))
		{
			encoding = "UTF-8";
		}
		else if (isUtf16leBom(bom, bomLength))
		{
			encoding = "UTF-16";
			wrapper.reset();
			wrapper.read(bom, 0, 2);
		}
		else if (isUtf16beBom(bom, bomLength))
		{
			throw new UnsupportedEncodingException("This parser does not support big-endian UTF-16");
		}
		else
		{
			encoding = "UTF-8";
			wrapper.reset();
		}
		delegate = new BufferedReader(new InputStreamReader(wrapper, encoding));
	}

	private boolean isUtf8Bom(byte[] bom, int bomLength)
	{
		return bomLength >= 3 && bom[0] == (byte) 0xef && bom[1] == (byte) 0xbb && bom[2] == (byte) 0xbf;
	}

	private boolean isUtf16leBom(byte[] bom, int bomLength)
	{
		return bomLength >= 2 && bom[0] == (byte) 0xff && bom[1] == (byte) 0xfe;
	}

	private boolean isUtf16beBom(byte[] bom, int bomLength)
	{
		return bomLength >= 2 && bom[0] == (byte) 0xfe && bom[1] == (byte) 0xff;
	}

	public String getEncoding()
	{
		return encoding;
	}

}
